import "./loadOlm";
import matrixSDK from "matrix-js-sdk";
import { verifySignature as verify } from "matrix-js-sdk/lib/crypto/olmlib";
import { cloneDeep } from "lodash";
import {
    registerAccount,
    deactivateAccount,
    loginAccount,
} from "./account";
import { createNewRoom } from "./room";
import { uploadFile, downloadFile } from "./file";
// import switchOffConsoleLog from "./helpers/consoleLogWithSwitch";

/**
 *
 *
 * @class SimpleClient
 */
class SimpleClient {
    /**
     *Creates an instance of SimpleClient.
     * @param {*} baseURL
     * @memberof SimpleClient
     */
    constructor({
        baseURL, deviceID, userID,
    }) {
        this.client = matrixSDK.createClient({
            baseUrl: baseURL,
            deviceId: deviceID,
            userId: userID,
            sessionStore: () => { }, // stub
        });

        // extend(this, client);
    }

    /**
     *
     *
     * @memberof SimpleClient
     */
    start() {
        this.client.startClient();
    }

    /**
     *
     *
     * @memberof SimpleClient
     */
    stop() {
        this.client.stopClient();
    }

    // Account operations
    /**
     *
     *
     * @param {*} username
     * @param {*} password
     * @param {*} session
     * @returns 
     * @memberof SimpleClient
     */
    register(username, password, session) {
        return registerAccount(this.client, username, password, session);
    }

    /**
     *
     *
     * @param {*} username
     * @param {*} password
     * @returns 
     * @memberof SimpleClient
     */
    login(username, password) {
        return loginAccount(this.client, username, password);
    }

    // 目前还无法完全删除该账户，所以重新注册会显示用户ID已被占用
    /**
     *
     *
     * @param {*} username
     * @param {*} password
     * @returns 
     * @memberof SimpleClient
     */
    deactivate(username, password) {
        return deactivateAccount(this.client, username, password);
    }

    createRoom({
        visibility, aliasName, topic, invitees,
    }) {
        if (!this.client.getAccessToken()) {
            return Promise.reject(new Error("Required login first !"));
        }
        const options = {};
        if (visibility) options.visibility = visibility;
        if (aliasName) options.room_alias_name = aliasName;
        if (topic) options.topic = topic;
        if (invitees) options.invite = invitees;

        return createNewRoom(this.client, options);
    }

    // file operations
    upload(file) {
        return uploadFile(this.client, file);
    }

    download(serverName, fileID) {
        return downloadFile(this.client, serverName, fileID);
    }

    // invite() {
    // }

    // Crypto operations
    async signObject(obj) {
        const objSigned = cloneDeep(obj);
        await this.client._crypto._signObject(objSigned);
        return objSigned;
    }

    async verifySignature(objSigned) {
        const obj = cloneDeep(objSigned);
        const { signatures } = obj;
        if (!signatures) throw new Error("The signatures filed is required");
        const [userId] = Object.keys(signatures);
        const [algAndDeviceId] = Object.keys(signatures[userId]);
        const [, deviceId] = algAndDeviceId.split(":");
        let deviceInfo = await this.client.getStoredDevice(userId, deviceId);
        if (!deviceInfo) {
            await this.client.downloadKeys([userId], true);
            deviceInfo = await this.client.getStoredDevice(userId, deviceId);
            if (!deviceInfo) throw new Error("Miss the public key to verify the signature");
        }
        const pubKey = deviceInfo.getFingerprint();
        try {
            await verify(
                this.client._crypto._olmDevice,
                obj,
                userId,
                deviceId,
                pubKey,
            );
            return true;
        } catch (e) {
            console.error(e);
            return false;
        }
    }
}

export default SimpleClient;

// switchOffConsoleLog(false);
